#include "bananaloader.h"
#include "rs232.h"

/* Funkcja konwertujaca znak na odpowiadajaca
   mu liczbe szesnastkowa */
uint8_t char_to_hex(const uint8_t x)
{
    if ( x >= '0' && x <= '9' )
        return x - '0';
    else if ( x >= 'A' && x <= 'F' )
        return x - 'A' + 0x0a;
    else if ( x >= 'a' && x <= 'f' )
        return x - 'a' + 0x0a;
    else
        return 0x00;
}

/* Funkcja pobiera dwa znaki, konwertuje je na 4-bitowe
   liczby, nastepnie tworzy z nich jedna 8 bitowa */
uint8_t USART_Get_Byte(void)
{
    uint8_t tmp1 = (char_to_hex(USART_Receive()) << 4);
    uint8_t tmp2 = char_to_hex(USART_Receive());
    return tmp1 | tmp2;
}

uint8_t Get_Byte_From_Buffer(void)
{
    if (ilosc==0)
    {

        /* Rozpoczecie odbioru*/
        USART_Transmit(XON);

        /* Pobranie dwukropka */
        tmp = USART_Receive();

        /* Ilosc bajtow w linii*/
        ilosc = USART_Get_Byte();

        /* Pobranie adresu */
        tmp = USART_Receive();
        tmp = USART_Receive();
        tmp = USART_Receive();
        tmp = USART_Receive();

        /* Pobranie bajtu okreslajacego rodzaj instrukcji
           0x00 - zwykle instrukcje
           0x01 - ostatnia linia
           */
        tmp = USART_Get_Byte();
        if (tmp == 0x00)
        {
            koniec = 0;

            for (int i=0; i<ilosc; i++)
                BUFOR[i] = USART_Get_Byte();

            /*Suma kontrolna*/
            tmp = USART_Receive();
            tmp = USART_Receive();

            /*Znak nowej linii*/
            tmp = USART_Receive();
            tmp = USART_Receive();
            aktualny=0;

            /* przeslij znak potwierdzajacy pomyslne pobranie linii */
            USART_Transmit('X');
        }
        else koniec = 1;

        /* Zakonczenie odbioru */
        USART_Transmit(XOFF);
    }

    tmp = BUFOR[aktualny];
    ilosc--;
    aktualny++;

    /* jesli nastapil koniec pliku, musimy reszte wypelnic 0xff */
    if (koniec) return 0xff;
    else return tmp;
}

static void __vectors(
    void )

{
    /* skok do sekcji .init2 (konieczny ze wzgl鹽u na umieszczanie stalych z
     * pami鹹i programu pomiedzy sekcjami .vectors a .init0, a wiec na samym
     * poczｹtku programu w przypadku wykorzystania opcji -nostartfiles */
    asm (
        "rjmp __init2" "\n\t"
    : : );
}


static void __init2(
    void )
{
    /* inicjalizacja wskaznika stosu, rejestru z zerem i rejestru flag */
    asm volatile (
        "out __SP_L__, %A0" "\n\t"
        "out __SP_H__, %B0" "\n\t"
        "clr __zero_reg__" "\n\t"
        "out __SREG__, __zero_reg__" "\n\t"
    : : "r"( ( uint16_t )( RAMEND ) ) );
}


static void __init9(
    void )
{
    /* skok do funkcji main */
    asm (
        "rjmp main" "\n\t"
    : : );
}

